perm filename DVIMAG.C[MF,ALS] blob sn#771995 filedate 1984-10-12 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00014 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	∂12-Oct-84  1323	trickey@diablo 	dvi-imagen    
C00004 00003	dvi-imagen.c
C00046 00004	output.c
C00068 00005	error.c
C00071 00006	rotate.c
C00073 00007	special.c
C00079 00008	imPcodes.h
C00081 00009	impress.h
C00083 00010	dvi.h
C00086 00011	c.h
C00088 00012	font.h
C00092 00013	ipr.h
C00096 00014	resfonts.h
C00097 ENDMK
C⊗;
∂12-Oct-84  1323	trickey@diablo 	dvi-imagen    
Received: from SU-AIMVAX.ARPA by SU-AI.ARPA with TCP; 12 Oct 84  13:23:31 PDT
Date: Fri, 12 Oct 84 13:24:17 pdt
From: Howard Trickey <trickey@diablo>
Subject: dvi-imagen
To: als@sail

Here are the files used for the VAX UNIX version of dvi-imagen,
a program that takes dvi files into the format used by imagen,
using pixel versions of the fonts.  The file produced by dvi-imagen
needs some additional ascii header information prepended to it before it
is sent to the imagen.  DRF probably knows that stuff, but I can help you
later if need be.

The files below are separated by lines of ==='s, with the file name.
The .c programs are C language, the .h files get included in them.

dvi-imagen.c
===============================================
/*
**      dvi-imagen.c    Imagen driver for DVI format 2
**
**  Syntax:
**      dvi-imagen [options] <dvi-file>
**
**  Description:
**      Translates the DVI commands in the <dvi-file> into commands
**      for the Imagen ImPrint-10 Laser Printer.  These are placed
**      into a /tmp file which is then handed to the ipr(1) program.
**
**	The -L option takes a shot at Landscape mode.
**	The -U option disables centering
**	The -I option provides one-inch margins
**      The -v option makes the output be in decoded (verbose) form
**              -v implies -s
**      The -s option makes dvi-imagen refrain from calling ipr(1),
**		with Impress output on stdout.
**	The -cX option requests X copies (default 1)
**      The -d option makes dvi-imagen produce debugging information.
**      The -D option gets everything -d does and more, including
**          dumping out the glyphs in each font in a readable format.
*/

#include <stdio.h>
#include <curses.h>
#include <pwd.h>
#include "dvi.h"
#include "font.h"

#define MAXFONTS    64      /* Due to 6-bit field in Imagen codes */
                            /* I may fix this in the next version */
			    
#define PIXELS←PER←INCH      300
#define HARD←XPAGE←OFFSET    160     /* Damn it */
#define PIXELS←PER←LINE      (8 * PIXELS←PER←INCH - HARD←XPAGE←OFFSET)
                                     /* 8 inches of printing area */
#define PIXELS←PER←PAGE      (11 * PIXELS←PER←INCH)
                                     /* 11 inches of printing area */
#define FONT←DIRECTORY       "/usr/stanford/lib/tex82/fonts/pxls"

#define pixel←round(x)      ((long) (conv * (double) (x) + 0.5))
#define dvi←round(x)        ((long) ((double) (x) / conv + 0.5))

#define one(fp)     num (fp, 1)
#define sone(fp)    snum(fp, 1)
#define two(fp)     num (fp, 2)
#define four(fp)    num (fp, 4)
#define sfour(fp)   snum(fp, 4)

typedef unsigned char   ubyte;

struct frame
{
        long    pxl←h, dvi←h, pxl←v, dvi←v, w, x, y, z;
};

struct frame    *stack;
int             stackp;

extern int	landscape;

int         debug = 0;
int         verbose = 0;
int         spoolit = 1;
int	    landscape = 0;
int	    center = 1;
int         inchmargin = 0;
int	    numcopies = 1;
struct font *fontListHead = NULL;
char        job←id[300];
char	    InputName[300];
int         total←pages, maxstack, Xpage←offset, Ypage←offset;
int         fontnum = 0;
double      conv;
long        numerator, denominator, magnification;
char        *output←file←name;
char        *Usage←str = "Usage: iptex [-U] [-I] [-L] [-v] [-s] [-d] <dvi-file>";

long            read←postamble();
unsigned long   num();
long            snum();
char            *malloc();
char            *mktemp();

main(argc, argv)
int     argc;
char    *argv[];
{
        FILE    *fp;
	long    last←page;     /* file offset of last page of output */
	int	nc;

        while (argv[1][0] == '-')
	{
	    switch (argv[1][1])
	    {
		case 'c':
		    if ((nc=atoi(&argv[1][2])) > 0) numcopies=nc;
		    break;
		    
		case 's':
                    spoolit = 0;
                    break;
                    
	        case 'd':
                    debug = 1;
                    break;
                
                case 'D':
                    debug = 2;
                    break;
                
                case 'v':
                    verbose = 1;
                    spoolit = 0;
                    break;

		case 'L':
		    landscape = 1;
		    break;

		case 'U':
		    center = 0;
		    break;

		case 'I':
		    inchmargin = 1;
		    break;
                
                default:
                    error(Usage←str);
	    }
            
            argv++;
            argc--;
	}
        
        if (argc != 2)
            error(Usage←str);

	if ((fp = fopen(argv[1], "r")) == NULL) {
	    char longername[256];
	    strcpy (longername, argv[1]);
	    strcat (longername, ".dvi");
	    if ((fp = fopen (longername, "r")) == NULL)
		error("dvi-imagen: Can't open %s", argv[1]);
	}
	strcpy (InputName, argv[1]);
	    
	process←preamble(fp);
	
	find←postamble(fp);
	
	last←page = read←postamble(fp);
	
	start←output();
	
	do←pages(fp, last←page);
	
	finish←output();
}

!
/*
**      process←preamble(fp)
**
**      fp is a FILE pointer for a DVI file which is positioned at the
**      beginning.
**
**      process←preamble reads the information in the preamble and stores
**      it into global variables for later use.
*/

process←preamble(fp)
FILE    *fp;
{
        ubyte   k;
	double  fraction;

        if (one(fp) != PRE)
	    error("dvi-imagen: DVI file doesn't start with preamble");
	    
	if (one(fp) != 2)
	    error("dvi-imagen: Wrong version of DVI output for this program");
	
	numerator     = four(fp);
	denominator   = four(fp);
	magnification = four(fp);
	
	fraction = (((double) numerator * magnification)
	                                 / ((double) denominator * 1000.));
	
	conv = ((fraction / 100000) / 2.54) * PIXELS←PER←INCH;
	
	k = one(fp);
	fread(job←id, sizeof(char), k, fp);
	job←id[k] = '\0';
}

!
/*
**      find←postamble(fp)
**
**      fp is a FILE pointer for a DVI-format file.  find←postamble locates
**      the beginning of the postamble and leaves the file ready to start
**      reading at that location.
*/

find←postamble(fp)
FILE    *fp;
{
        ubyte   byte;
	long    offset = -4;        /* At least 4 TRAILERS */
	
	do
	{
	    offset--;
	    fseek(fp, offset, 2);
	    byte = one(fp);
	} while(byte == TRAILER);
	
	if (byte != 2)
	    error("dvi-imagen: Wrong version of DVI output for this program");
	
	offset -= 4;
	fseek(fp, offset, 2);

	fseek(fp, four(fp), 0);
}

!
/*
**      long
**      read←postamble(fp)
**
**      fp is a FILE pointer for a DVI-format file.  read←postamble reads the
**      information in the postamble, storing it into global variables.
**      It also takes care of reading in all of the PXL files for the fonts
**      used in the job.
**
**      read←postamble returns the file offset of the beginning of the last
**      page of DVI output.
*/

long
read←postamble(fp)
FILE    *fp;
{
        long    last←page;
        long    tallest, widest;
        ubyte   cmnd;

        if (one(fp) != POST)
	    error("dvi-imagen: Postamble doesn't begin with POST");
	
	last←page = four(fp);
	
	if (numerator != four(fp)
	          ||  denominator != four(fp)
		  ||  magnification != four(fp))
	    error("dvi-imagen: Postamble doesn't match preamble");
	      
	tallest      = four(fp);
	if (!landscape) {
	    Ypage←offset = (PIXELS←PER←PAGE - pixel←round(tallest)) / 2;
	    widest       = four(fp);
	    Xpage←offset = (PIXELS←PER←LINE - pixel←round(widest)) / 2
                                                        + HARD←XPAGE←OFFSET;
	} else {
	    Ypage←offset = (PIXELS←PER←LINE - pixel←round(tallest))/2
					+ HARD←XPAGE←OFFSET;
	    widest       = four(fp);
	    Xpage←offset = (PIXELS←PER←PAGE - pixel←round(widest))/2;
	}

	if (!center) Ypage←offset = Xpage←offset = 0;

	if (inchmargin) Ypage←offset = Xpage←offset = PIXELS←PER←INCH;
	    
	maxstack     = two(fp);
	total←pages  = two(fp);
        
        if (debug)
            remark("tall, wide, po, stk, pages = %d, %d, %d, %d, %d",
                    tallest, widest, Xpage←offset, maxstack, total←pages);
	
	do
	{
	    switch(cmnd = one(fp))
	    {
	        case FNTDEF1:
	        case FNTDEF2:
	        case FNTDEF3:
	        case FNTDEF4:
		    define←font(fp, cmnd);
		    break;
		    
		case POSTPOST:
		    break;
		
		default:
		    error("dvi-imagen: Non-fntdef cmnd found in postamble");
	    }
	} while (cmnd != POSTPOST);
	
	return (last←page);
}

!
/*
**      define←font(fp, cmnd)
**
**      fp is a FILE pointer for a DVI file which is positioned right after
**      a fntdef command.  The opcode for the command is in cmnd.
**
**      define←font reads the rest of the fntdef command and then reads in
**      the specified PXL file, adding it to the global linked-list holding
**      all of the fonts used in the job.
*/

define←font(fp, cmnd)
FILE    *fp;
ubyte   cmnd;
{
        struct font *fontp;
	long        checksum;
	int         len;
	char        fontname[513];
	
	if (fontnum >= MAXFONTS)
	    error("dvi-imagen: Too many fonts.  Maximum is %d", MAXFONTS);
	
	fontp = (struct font *) malloc( sizeof(struct font) );
	
	if (fontp == NULL)
	    error("dvi-imagen: Out of memory while reading font %d", fontnum);

	fontp->next      = fontListHead;
	fontListHead     = fontp;
	
        fontp->TeXnumber = num(fp, cmnd - FNTDEF1 + 1);
	fontp->Inumber   = fontnum++;
	
	checksum = four(fp);
	
	fontp->scale     = four(fp);
	fontp->design    = four(fp);
	
	len = one(fp) + one(fp);
	fread(fontname, sizeof(char), len, fp);
	fontname[len] = '\0';
        strcpy(fontp->fontname, fontname);
        
	read←pxl←file(fontp, fontname);
        
        if (debug > 1)
            dump←font(fontp, fontname);
}

!
/*
**      read←pxl←file(fontp, fontname)
**
**      fontp points to a (struct font) which has been partially initialised
**      with the information in the DVI-file FNTDEF command.  fontname is the
**      name of a font.
**
**      read←pxl←file constructs the expected name of the font's PXL file
**      from the info in *fontp and fontname.  It then reads the glyph
**      bitmaps into memory.
**
**      Note: the 'size' of a font (i.e. the 1200 in 'cmr10.1200pxl') is
**      given by the following formula (rounded):
**
**              scaled-size   PIXELS←PER←INCH
**              ----------- * --------------- * 1000
**              design-size         200
**
**	In the actual implementation, scaled-size/design-size hasn't been
**	stored with sufficient precision, hence the messing around to find
**	its actual value.
*/
char *rotate();

read←pxl←file(fontp, fontname)
struct font     *fontp;
char            *fontname;
{
        char    filename[1025];
	FILE    *pxlfp;
	int	unmodsize;
	float	realsize;
	int     size;
        long    checksum, magnify,
                design←size, font←dir←ptr, pxl←id←word;
        long    glyph←ptr[128];     /* Seek locations of each glyph */
        int     i, j, k;
	
	realsize = (magnification/1000.)*((float) fontp->scale / fontp->design);
	unmodsize = (realsize * 1000) + 0.5;
	/* a real hack to correct for rounding in some cases -- rkf */
	if(unmodsize==1095) realsize = 1.095445;	/* stephalf */
	else if(unmodsize==1315) realsize=1.314534;	/* stepihalf */
	else if(unmodsize==2074) realsize=2.0736;	/* stepiv */
	else if(unmodsize==2488) realsize=2.48832;	/* stepv */
	else if(unmodsize==2986) realsize=2.985984;	/* stepiv */
	/* the remaining magnification steps are represented with sufficient
		accuracy already */
	size = (realsize * PIXELS←PER←INCH * 5) + 0.5;
	
	sprintf(filename, "%s.%dpxl", fontname, size);
	
	if ((pxlfp = fopen(filename, "r")) == NULL)
	{
	    sprintf(filename, "%s/%s.%dpxl", FONT←DIRECTORY, fontname, size);
	    
	    if ((pxlfp = fopen(filename, "r")) == NULL)
            {
	        remark("scale = %d, design = %d",fontp->scale, fontp->design);
	        fperror("Can't find font: \"%s\"", filename);
            }
	}

	fseek(pxlfp, - (5 * 4L), 2);        /* Seek to trailer info   */
        checksum      = four(pxlfp);
        magnify = four(pxlfp);
        design←size   = four(pxlfp);
        font←dir←ptr  = four(pxlfp) * 4;
        pxl←id←word   = four(pxlfp);

	fseek(pxlfp, font←dir←ptr, 0);      /* Seek to font directory */
        
        fontp->bc = 0;
        fontp->ec = 127;
	for (i=0; i < 128; i++)
	{
            fontp->state[i] = Ready;
	    fontp->W[i]     = two(pxlfp);
	    fontp->H[i]     = two(pxlfp);
	    fontp->X[i]     = two(pxlfp);
	    fontp->Y[i]     = two(pxlfp);
            glyph←ptr[i]    = four(pxlfp) * 4;
                    /*
                    **  The TFM-width word is kind of funny in the units
                    **  it is expressed in.  It works this way:
                    **
                    **  If a glyph has width 'w' in a font with design-size
                    **  'd' (both in same units), the TFM-width word is
                    **
                    **                    (w/d) * 2↑20
                    **
                    **  Therefore, in order to find the glyph width in
                    **  DVI units (1 / 2↑16 points), we take the design-size
                    **  'd' (in DVI's), the magnification 'm' of the PXL file
                    **  and the TFM-width word 't' to the width (in DVI's)
                    **  as follows:
                    **
                    **                     dmt
                    **                w = -----
                    **                    2↑20
                    **
                    **  But the magnification of the PXL file is just the
                    **  scaled size 's' over the design size, so the final
                    **  expression for the width is
                    **
                    **                     st
                    **                w = ----
                    **                    2↑20
                    **
                    */      
#ifndef UNDEFINED
            fontp->dvi←adv[i] =
                    ((double) fontp->scale * four(pxlfp)) / (1 << 20);
#else
            fontp->dvi←adv[i] =
                    ((double) fontp->design * four(pxlfp)) / (1 << 20);
#endif
            fontp->pxl←adv[i] = pixel←round(fontp->dvi←adv[i]);
	}
        
        for (i=0; i < 128; i++)
	{
            int     real←bytes←wide = (fontp->W[i] + 7) / 8;
            int     file←bytes←wide = ((fontp->W[i] + 31) / 32) * 4;
            char    *ptr;
            char    junk;
            
            ptr = fontp->Glyph[i] = malloc(fontp->H[i] * real←bytes←wide);
            if (ptr == NULL)
                error("Out of memory while reading character %d of font %s\n",
                                                                 i, fontname);
	    fseek(pxlfp, glyph←ptr[i], 0);
            for (j=0; j < fontp->H[i]; j++)
	    {
	        for (k=0; k < file←bytes←wide; k++)
		{
		    if (k < real←bytes←wide)
                        *(ptr++) = one(pxlfp);
                    else
                        junk = one(pxlfp);
		}
	    }
	    if (landscape) {
		char	*holdglyph;
		int	width,height,x,y;

		holdglyph = fontp->Glyph[i];
		fontp->Glyph[i] = rotate(holdglyph, fontp->H[i], fontp->W[i]);
	/*	free(holdglyph); */
		width = fontp->W[i]; height=fontp->H[i];
		x = fontp->X[i]; y=fontp->Y[i];
		fontp->W[i] = height; fontp->H[i] = width;
		fontp->X[i] = height-y; fontp->Y[i] = x;
	    }
		
	}
        fclose(pxlfp);
}

!
/*
**              start←output()
**
**      Arrange for the stuff at the beginning of the output to the Imagen
**      to be sent out, including the jobid, etc.
**
*/

start←output()
{
        char            *buffer[50];
        struct passwd   *pwbuf, *getpwuid();
        
        pwbuf = getpwuid(getuid());
        sprintf(buffer, " (%s [%d pages])", pwbuf->pw←name, total←pages);
        strcat(job←id, buffer);
	if (spoolit) {
        	output←file←name = mktemp("/tmp/dviXXXXXX");
        	ImPressStart(output←file←name, job←id, verbose);
	}
	else
        	ImPressStart((char *)0, job←id, verbose);
	
}

!
/*
**              do←pages(fp, last←page)
**
**      Process the pages in the FILE fp.  last←pages is the offset of the
**      last page.  (We do the pages in reverse order, of course.)
**
*/

#define PXL←H   stack[stackp].pxl←h
#define PXL←V   stack[stackp].pxl←v
#define DVI←H   stack[stackp].dvi←h
#define DVI←V   stack[stackp].dvi←v
#define WW      stack[stackp].w
#define XX      stack[stackp].x
#define YY      stack[stackp].y
#define ZZ      stack[stackp].z

#define nope(str)       error("Can't hack %s", str)

#define correct()       diff = PXL←H - pixel←round(DVI←H);  \
                        if (diff < 0)                       \
		        {                                   \
		            while (diff++)                  \
                                ImPressMplus();             \
		        }                                   \
                        else if (diff > 0)                  \
		        {                                   \
		            while (diff--)                  \
                                ImPressMminus();            \
		        }                                   \
                        PXL←H = pixel←round(DVI←H);

do←pages(fp, last←page)
FILE    *fp;
long    last←page;
{
        char        input←left = 1;
        long        next←page;
        struct font *curr←font;
        int         diff;
        struct font *ptr;
        ubyte       ch;
                
        stack = (struct frame *) malloc( sizeof(struct frame) * (maxstack+1));
        
        if (stack == NULL)
            error("Can't allocate stack space.");
            
        fseek(fp, last←page, 0);
        
        while (input←left)
	{
            ch = one(fp);
            
 	    if (ch <= SETCHAR0 + 127)
	    {
                ImPressCharacter(ch);
                DVI←H += curr←font->dvi←adv[ch];
                PXL←H += curr←font->pxl←adv[ch];
                correct();
	    }
	    else if (FNTNUM0 <= ch  &&  ch <= FNTNUM0 + 63)
	    {
                for (ptr = fontListHead; ptr != NULL; ptr = ptr->next)
                    if (ptr->TeXnumber == ch - FNTNUM0)
                        break;
                
                if (ptr == NULL)
                    error("FNTNUM to non-existant font #%d", ch - FNTNUM0);
                
                curr←font = ptr;
                ImPressFont(ptr);
            }
	    else
	    {
                long    a, b;
                
		switch (ch)
		{
		    case SET1:
                        nope("SET1");
			break;

		    case SETRULE:
			a = sfour(fp); b = sfour(fp);
                        if (a > 0  &&  b > 0)
			{
			    correct();
                            ImPressRule(pixel←round(b), pixel←round(a));
			}
			DVI←H += b;
                        diff = pixel←round(DVI←H);
                        ImPressMove(diff - PXL←H);
                        PXL←H = diff;
			break;

		    case PUT1:
			nope("PUT1");
			break;

		    case PUTRULE:
			a = sfour(fp); b = sfour(fp);
                        if (a > 0  &&  b > 0)
			{
			    correct();
                            ImPressRule(pixel←round(b), pixel←round(a));
			}
			break;

		    case NOP:
			break;

		    case BOP:
                        a = four(fp);
			if (debug)
                            remark("Beginning page %d", a);
			for (a=0; a < 9; a++)
			    four(fp);
                        next←page = sfour(fp);
                        stackp = 0;
                        DVI←H = dvi←round(Xpage←offset);
                        PXL←H = Xpage←offset;
                        DVI←V = dvi←round(Ypage←offset);
                        PXL←V = Ypage←offset;
                        WW = XX = YY = ZZ = 0;
                        curr←font = NULL;
                        ImPressBeginPage();
                        ImPressSetX(PXL←H);
			break;

		    case EOP:
                        ImPressEndPage();
                        if (stackp > 0)
                            remark("Stack not empty at EOP; stackp = %d",
                                                                      stackp);
                        if (next←page < 0)
                            input←left = 0;
                        else
                            fseek(fp, next←page, 0);
			break;

		    case PUSH:
                        stackp++;
                        if (stackp > maxstack)
                            error("More PUSHes than were promised");
                        stack[stackp] = stack[stackp - 1];
			break;

		    case POP:
                        stackp--;
                        if (stackp < 0)
                            error("More POPs than PUSHes");
                        ImPressSetX(PXL←H);
                        ImPressSetY(PXL←V);
			break;

		    case RIGHT1:
		    case RIGHT2:
		    case RIGHT3:
		    case RIGHT4:
			DVI←H += snum(fp, ch - RIGHT1 + 1);
                        diff = pixel←round(DVI←H);
                        ImPressMove(diff - PXL←H);
                        PXL←H = diff;
			break;

		    case X0:
		    case X1:
		    case X2:
		    case X3:
		    case X4:
			if (ch != X0)
                        {
			    XX = snum(fp, ch - X0);
                            ImPressSetSpace(pixel←round(XX));
                        }
                        ImPressSpace();
                        DVI←H += XX;
                        PXL←H += pixel←round(XX);
                        correct();
			break;

		    case W0:
		    case W1:
		    case W2:
		    case W3:
		    case W4:
			if (ch != W0)
			    WW = snum(fp, ch - W0);
			DVI←H += WW;
                        diff = pixel←round(DVI←H);
                        ImPressMove(diff - PXL←H);
                        PXL←H = diff;
			break;

		    case Y0:
		    case Y1:
		    case Y2:
		    case Y3:
		    case Y4:
			if (ch != Y0)
			    YY = snum(fp, ch - Y0);
			DVI←V += YY;
                        PXL←V = pixel←round(DVI←V);
                        ImPressSetY(PXL←V);
			break;

		    case Z0:
		    case Z1:
		    case Z2:
		    case Z3:
		    case Z4:
			if (ch != Z0)
			    ZZ = snum(fp, ch - Z0);
			DVI←V += ZZ;
                        PXL←V = pixel←round(DVI←V);
                        ImPressSetY(PXL←V);
			break;

		    case DOWN1:
		    case DOWN2:
		    case DOWN3:
		    case DOWN4:
			DVI←V += snum(fp, ch - DOWN1 + 1);
                        PXL←V = pixel←round(DVI←V);
                        ImPressSetY(PXL←V);
			break;

		    case FNT1:
		    case FNT2:
		    case FNT3:
		    case FNT4:
			a = num(fp, ch - FNT1 + 1);
                        for (ptr = fontListHead; ptr != NULL; ptr = ptr->next)
                            if (ptr->TeXnumber == a)
                                break;
                
                        if (ptr == NULL)
                            error("FNT to non-existant font #%d", a);
                
                        curr←font = ptr;
                        ImPressFont(ptr);
			break;

		    case XXX1:
		    case XXX2:
		    case XXX3:
		    case XXX4:
                        /*nope("XXXX");*/
			a = num(fp, ch-XXX1+1);
			if(a > 0)
			    DoSpecial (a, fp);
			break;

		    case FNTDEF1:
		    case FNTDEF2:
		    case FNTDEF3:
		    case FNTDEF4:
                        fseek(fp, 12 + ch - FNTDEF1 + 1, 1);
                        a = one(fp) + one(fp);
                        fseek(fp, a, 1);
			break;

		    case PRE:
                        error("Can't Happen:  PRE encountered.");
			break;

		    case POST:
                        error("Can't Happen:  POST encountered.");
			break;

		    case POSTPOST:
                        error("Can't Happen:  POSTPOST encountered.");
			break;
		    
		    default:
			error("Unknown Op-code: %d; Offset: %d",
                                                               ch, ftell(fp));
		} /* end switch*/
	    } /* end else (ch not a SETCHAR or FNTNUM) */
	} /* end while */
}

!
/*
**              finish←output()
**
**      Wrap it up.  This routine does not return, since ImPressSendIt()
**      doesn't.
**
*/

finish←output()
{
        ImPressFinish();
        if (! spoolit)
            exit(0);
        ImPressSendIt(output←file←name, NULL, InputName,
			total←pages, numcopies, 0, 0);
}

!
/*
**              num(fp, size)       snum(fp, size)
**
**      Read size bytes from the FILE fp, constructing them into a
**      signed/unsigned integer.
**
*/

unsigned long
num(fp, size)
FILE    *fp;
int     size;
{
        int     i;
	long    x;
	
	x = 0;
	for (i=0; i < size; i++)
	{
	    x = x * 256 + (unsigned) fgetc(fp);
	}
	
	return(x);
}

long
snum(fp, size)
FILE    *fp;
int     size;
{
        int     i;
	long    x;
	
	x = fgetc(fp) & 0377;
        if (x & 0200)
            x -= 256;
            
	for (i=1; i < size; i++)
	{
	    x = x * 256 + (unsigned) fgetc(fp);
	}
	
	return(x);
}

!
/*
**              dump←font(fontp, fontname)
**
**      Debugging routine which prints a representation of the information
**      read from a PXL file into a 'struct font'.
**
*/

dump←font(fontp, fontname)
struct  font    *fontp;
char            *fontname;
{
	int     i, j, k, l;
        
        printf("\n+++++DUMP OF FONT \"%s\":  ", fontname);
        printf("TeXnumber, Inumber, scale, design = %d, %d, %d, %d\n",
                        fontp->TeXnumber,
                        fontp->Inumber,
                        fontp->scale,
                        fontp->design);
        printf("\tfontp = %o\n", fontp);
        
        for (i=0; i < 128; i++)
	{
	    char    *ptr;
            
	    printf("\nCharacter %d (%s):  ", i, unctrl(i));
            printf("H, W, X, Y = %d, %d, %d, %d\n",
                        fontp->H[i],
                        fontp->W[i],
                        fontp->X[i],
                        fontp->Y[i]);
            printf("\t\tdvi←adv, pxl←adv = %d, %d\n\n",
                        fontp->dvi←adv[i],
                        fontp->pxl←adv[i]);
            
	    ptr = fontp->Glyph[i];
            for (j=0; j < fontp->H[i]; j++)
	    {
	        for (k=0; k < (fontp->W[i] + 7) / 8; k++)
		{
		    for (l=7; l >= 0; l--)
		    {
		        if (*ptr & (1 << l))
                            putchar('@');
                        else
                            putchar(' ');
		    }
                    
                    ptr++;
		}
                
                putchar('\n');
	    }
	}
}

output.c
===============================================
/*
 * output.c - implements the ImPress output primitives
 *	This is the verbose (decoded) version,
 *	along with the encoded version, default unless
 *	
 *
 * written by Bill Nowicki, September 1981
 * Stanford University
 *
 * January 1982		Bill Nowicki
 *	- Added page buffering
 *	- Added glyph deletion
 */
 
# include <stdio.h>
# include "font.h"
# include "imPcodes.h"
# include "ipr.h"
# include "impress.h"

static struct font *CurrentFont = NULL;
static FILE        *imPressFile = NULL;
static int         Verbose = 0;
static int         MemoryAvailable = GlyphSize;
static int         MemoryNeeded = 0;

extern int	landscape;

  /*
   * The page buffer.  A list of Glyphs, i.e. (font,char) pairs
   * that are needed on this page, and a list of the actual typesetting
   * commands.
   */
static struct font *GlyphTable[GlyphsPerPage];
static char GlyphChars[GlyphsPerPage];
static char PageBuffer[InputSize];
static int GlyphPointer = 0, PagePointer = 0;

ImPressPutc( c )
  {
  	/*
	 * Put the indicated character into the page buffer
	 */
    if (PagePointer>=InputSize) fprintf( stderr, "Input Area overflow\n");
    PageBuffer[PagePointer++] = c;
  }


ImPressBufWord( w )
 {
 	/*
	 * output a (big-endian) word to the ImPress page buffer
	 */
   ImPressPutc( (w>>8)&0377 );
   ImPressPutc( (w)&0377 );
 }


ImPressPrintf( s, arg1, arg2, arg3, arg4, arg5 )
  {
    /*
     * printf the string with arguments into the page buffer
     */
    char buf[512];
    int len;
    sprintf( buf, s, arg1, arg2, arg3, arg4, arg5 );
    len = strlen(buf);
    if (PagePointer+len>=InputSize) fprintf( stderr, "Input Area overflow\n");
    strncpy( PageBuffer+PagePointer, buf, len);
    PagePointer += len;
  }


ImPressFont( f )
 struct font *f;
  {
     /*
      * switch to font f
      */
    if (CurrentFont == f) return;
    if (Verbose)  ImPressPrintf(  "@F %d@", f->Inumber );
        else {
	       ImPressPutc( AF );
	       ImPressPutc( f->Inumber );
	     }
     CurrentFont = f;
  }


ImPressMplus()
{
    if (Verbose)
        ImPressPrintf("@MPLUS@");
    else
        ImPressPutc( AMP );
}


ImPressMminus()
{
    if (Verbose)
        ImPressPrintf("@MMINUS@");
    else
        ImPressPutc( AMM );
}

ImPressMove( deltaX )
  {
    /*
     * Move the X (major axis) coordinate 
     */
   
   if (-128 <= deltaX  &&  deltaX <= 127)
   {
     if (Verbose) ImPressPrintf(  "@M %d@\n", deltaX);
      else {
	     ImPressPutc( AM );
	     ImPressPutc( deltaX );
	     ImPressPutc( AM );
	   }
   } 
   else
   {
     if (Verbose) ImPressPrintf(  "@H %d 1@\n", deltaX);
      else {
	     ImPressPutc( AH );
	     ImPressPutc( (deltaX >> 7) & 0377 );
	     ImPressPutc( (deltaX << 1) & 0376 | 01 );
	   }
   }
  }


ImPressSetX( x )
  {
    /*
     * set the X (major axis) coordinate 
     */
     
     if (Verbose) ImPressPrintf(  "@H %d 0@\n", x);
      else {
	     ImPressPutc( AH );
	     ImPressPutc( (x>>7)&0377 );
	     ImPressPutc( (x<<1)&0376 );
	   }
  }


ImPressSetSpace( s )
  {
    /*
     * set the "word space" value
     */
     
     if (Verbose) ImPressPrintf(  "@SETSP %d@\n", s);
      else {
	     ImPressPutc( ASETSP );
	     ImPressBufWord( s );
	   }
     
  }


ImPressSpace()
  {
     /*
      * do a default word space
      */
    
     if (Verbose) ImPressPrintf(  "@SP0@\n" );
      else ImPressPutc( ASP0 );
  }


ImPressSetY(y)
  {
    /*
     * set the Y (minor axis) coordinate 
     */
     
     
     if (Verbose) ImPressPrintf(  "@V %d 0@\n", y);
      else {
	     ImPressPutc( AV );
	     ImPressPutc( (y>>7)&0377 );
	     ImPressPutc( (y<<1)&0376 );
	   }
  }


ImPressCharacter( c )
 char c;
  {
    /*
     * Output the character c in the current font at the current
     * position.  First we check its state (loaded, wanted, etc.)
     */

   switch (CurrentFont->state[c])
       {
        case Ready:
         	CurrentFont->state[c]=Wanted;
		GlyphChars[GlyphPointer  ]=c;
		GlyphTable[GlyphPointer++]=CurrentFont;
		MemoryNeeded += ImPressSize( CurrentFont, c );
		break;


        case Loaded:
         	CurrentFont->state[c]=Kept;
		GlyphChars[GlyphPointer  ]=c;
		GlyphTable[GlyphPointer++]=CurrentFont;
		break;

        case Wanted:
        case Kept:
        case InProm:
		break;
		
	default:
		remark("Weird state for character %d in font %s\n",
		                                   c, CurrentFont->fontname );
                abort(); 
       }
       
        if (Verbose && c=='@')
            ImPressPrintf( "@AT@" );
	else
            ImPressPutc( c );
   }
  


ImPressGlyph( f, c )
 struct font *f;
 unsigned char c;
  {
    register char *glyph = f->Glyph[c];
    int bytes = (f->W[c]+7) / 8;
    int row, col;

    /*
     * send the indicated glyph in the font f to the Imprint file.
     * "Small" glyphs have all dimensions less than eight bits.
     */
   if (f->W[c] == 0  ||  f->H[c] == 0)
	return;

   if (Verbose)  
   {
    if  ( abs(f->W[c]) < 128 && abs(f->H[c]) < 128 && 
	  abs(f->X[c]) < 128 && abs(f->Y[c]) < 128 )
	 fprintf( imPressFile,  "@SGLY" );
    else fprintf( imPressFile,  "@BGLY" );
    fprintf( imPressFile,  " 0 %d %d %d %d %d %d %d\n", f->Inumber, c, 
        f->pxl←adv[c], f->W[c], f->X[c], 
    	f->H[c], f->Y[c]);
    fprintf( imPressFile,  "f = %o, f->TeXnumber = %d\n", f, f->TeXnumber);

    for (row=0; row < f->H[c]; row++)
      {
        for (col=0; col<bytes; col++)
	  {
	    static char map[] = { '.', 'O' };

	    putc( map[ (*glyph >> 7) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 6) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 5) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 4) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 3) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 2) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 1) & 1 ], imPressFile );
	    putc( map[ (*glyph     ) & 1 ], imPressFile );
	    if (col&1) putc( ' ', imPressFile );
	    glyph++;
	  }
	if (bytes&1) fprintf( imPressFile,  "........" );
	putc( '\n', imPressFile );
      }
    	
     fprintf( imPressFile, "@\n" );
    }
    else
     {
        /*
	 * the encoded form of glyph loading
	 */
      int rotation;
      if (landscape) rotation = 0100; else rotation = 0;
      if  ( abs(f->W[c]) < 128 && abs(f->H[c]) < 128 && 
	   abs(f->X[c]) < 128 && abs(f->Y[c]) < 128 )
	  {
	    int temp;
	    putc( ASGLY, imPressFile );
	    putc(rotation | (f->Inumber>>1), imPressFile );
	    putc( ( (f->Inumber&1)<<7)|c, imPressFile );
	    putc( f->pxl←adv[c], imPressFile );
	    putc( f->W[c], imPressFile );
	    putc( f->X[c], imPressFile );
	    putc( f->H[c], imPressFile );
	    putc( f->Y[c], imPressFile );
	  }
       else
          {

	putc( ABGLY, imPressFile );
	putc(rotation | (f->Inumber>>1), imPressFile );
	putc( ((f->Inumber&1)<<7)|c, imPressFile );
	ImPressPutWord( f->pxl←adv[c] );
	ImPressPutWord( f->W[c] );
	ImPressPutWord( f->X[c] );
	ImPressPutWord( f->H[c] );
	ImPressPutWord( f->Y[c] );
       }
       fwrite( glyph, 1, f->H[c]*bytes, imPressFile );
     }
    f->state[c] = Loaded;
  }


ImPressRule( w, h )
  {
  	/*
	 * draw a rule (rectangle) at current point with given dimensions
	 */
    if (Verbose)
      {
        if ( abs(w) < 127 && abs(h) < 127 )
	      ImPressPrintf( "@SRULE" );
         else ImPressPrintf( "@BRULE" );
        ImPressPrintf(  " %d %d %d@\n", w, h, -h);
        return;
      }
      if ( abs(w) < 127 && abs(h) < 127 )
        {
	     ImPressPutc( ASRULE );
	     ImPressPutc( w );
	     ImPressPutc( h );
	     ImPressPutc(-h );
	     return;
	}
         ImPressPutc( ABRULE );
         ImPressBufWord( w );
	 ImPressBufWord( h );
	 ImPressBufWord(-h );
  }


ImPressPutWord( w )
 {
 	/*
	 * output a (big-endian) word to the ImPress file
	 */
   putc( (w>>8)&0377, imPressFile );
   putc( (w)&0377, imPressFile );
 }


ImPressStart( fileName, jobID, verbosity )
 char *fileName;
 char *jobID;
 int verbosity;	
  {
    /*
     * open the indicated file name for imPress output
     * Verbosity is true to use the Verbose (decoded) mode.
     * Here we write a dummy job name and ImPress version.
     * Returns nonzero if it cannot open the file.
     */
    if (fileName == (char *)0) 
	imPressFile = stdout;
    else
    	imPressFile = fopen( fileName, "w" );
    if (imPressFile==NULL)
      {
        if (debug) printf( "Unable to open %s\n", fileName );
	return(TRUE);
      }
    Verbose = verbosity;
#ifdef OLDIMAGEN
    fprintf( imPressFile, "2 %s", jobID );
    putc( 0, imPressFile );
    fprintf( imPressFile, "12345678");
#endif
    if (landscape)
    {
	if(Verbose)
	{
	    fprintf(imPressFile,"@SET-HV-SYSTEM");
	    fprintf(imPressFile,"  %o\n",0101);
	}
	else
	{
	    fprintf(imPressFile,"%c%c",AMS,0101);
	}
    }
    MemoryNeeded = 0;
    MemoryAvailable = GlyphSize;
    return(FALSE);
  }


ImPressBeginPage()
 {
   /*
    * begin a page of an imPress file
    */
    PagePointer = 0;
    GlyphPointer = 0;
 }


ImPressEndPage()
 {
   /*
    * end a page of an impress file.
    *
    * First we delete glyphs we do not use on this page if necessary,
    * then output all the glyphs we need, then finally dump the Page buffer.
    */
     register char *glyphc;
     register struct font **fp;
     
     if (debug) 
        printf( "Begin page, Needed = %d, available = %d\n",
		 MemoryNeeded, MemoryAvailable );
     if (MemoryNeeded >= MemoryAvailable) ImPressDeleteGlyphs();

     for (glyphc=GlyphChars, fp=GlyphTable; glyphc < GlyphChars+GlyphPointer;
     		glyphc++, fp++)
	  switch ( (*fp)->state[ *glyphc] )
	    {
	      case Wanted:  ImPressGlyph( *fp, *glyphc );
	      default:	    (*fp)->state[ *glyphc ] = Loaded;
	    }
     MemoryAvailable -= MemoryNeeded;
    
     if (Verbose) fprintf( imPressFile, "@PAGE@\n" );
      else putc( APAGE, imPressFile );
     fwrite( PageBuffer, 1, PagePointer, imPressFile );
     if (Verbose) fprintf( imPressFile, "@END@\n" );
      else  putc( AEND, imPressFile );
     MemoryNeeded = 0;
 }


ImPressFinish()
 {
    /*
     * End and close out the imPress file
     */
    
     if (Verbose) fprintf( imPressFile, "@EOF@" );
      else putc( AEOF, imPressFile );
    fclose( imPressFile );
 }


ImPressSize( f, c )
 register struct font *f;
 register char c;
  {
  	/*
	 * Returns the size of a glyph in the ImPrint's memory.
	 * VERY dependent on the controller code.
	 */
    register int size;
    int bytes = (f->W[c]+7)/8;

    if ( ( f->pxl←adv[c] | f->W[c] | f->H[c] | abs(2*f->X[c]) | abs(2*f->Y[c]) ) < 256 ) 
          size = 12;
     else size = 16;
    size += bytes*f->H[c];
    if (bytes&1) size += f->H[c];
    if (bytes<=2 && f->H[c]&1) size += bytes;
    return(size);
  }
  

ImPressDeleteGlyphs()
  {
  	/*
	 * Make a pass through all the fonts we have loaded, 
	 * deleting those glyphs that are loaded but not needed onthis page.
	 */
    register struct font *f;
    register char c;
    
    for (f=fontListHead; f; f=f->next)
      for (c=f->bc;c<=f->ec;c++)
       if (f->state[c]==Loaded)
        {
	  if (Verbose) 
	      fprintf( imPressFile, "@DELG 0 %d %d @\n" , f->Inumber, c );
	   else
	     {
	       putc( ADELG, imPressFile );
	       putc( f->Inumber>>1, imPressFile );
	       putc( (f->Inumber&1)<<7|c, imPressFile );
	     }
	   MemoryAvailable += ImPressSize( f, c );
	   f->state[c] = Ready;
	}
    if (debug) 
      printf( "After Deleting glyphs, Memory Needed = %d bytes, Available = %d\n",
      MemoryNeeded, MemoryAvailable );
  }


ImPressSendIt( fileName, banner, inputName, numberPages, 
     numberCopies, writeFlag, mailFlag)
  char *fileName;		/* name of temporary file */
  char *banner;			/* banner */
  char *inputName;		/* name of input file */
  int   numberPages;		/* hint of length */
  int   numberCopies;		/* number of copies wanted */
  int   writeFlag;		/* write when done */
  int   mailFlag;		/* mail when done */
   {
	/*
	 * Use the ipr spooler to send fileName to an ImPress printer.
	 *  Use banner as the tag for the spooler, or inputName if banner is null.
	 * Note that this routine execs, so it should normally never return.
	 */
    char *tag;
    char  pages[20], copies[20];
    char *args[20];
    int   count = 0;

    if (banner) tag = banner;
    else if (inputName) tag = inputName;
    else tag = "stdin";

    args[count++] = "ipr";
    if (debug)     args[count++] = "-d";
    args[count++] = "-Limpress";
    args[count++] = "-Djobheader on";
    args[count++] = "-r";
    args[count++] = "-t"; 
    args[count++] = tag; 
    if (numberPages>0)
      {
        sprintf( pages, "-p%d", numberPages );
        args[count++] =  pages;
      }	
    if (numberCopies>0)
      {
        sprintf( copies, "-c%d", numberCopies );
        args[count++] =  copies;
      }	
    if (mailFlag)  args[count++] = "-m";
    if (writeFlag) args[count++] = "-n";
    args[count++] =  fileName;
    args[count++] =  NULL;
    if (debug)
      {
        int i;
        printf( "Command line: " );
	for (i=0; i<count; i++) printf( " %s", args[i] );
	putchar( '\n' );
	fflush(stdout);
      }
    execv( COMMAND, args );
    fperror("Couldn't execute ipr.  ImPress file in %s",fileName);
  }

error.c
===============================================
/*********************************************************************
function:	error
description:	Error message routines
programmer:	Alan S. Watt

history:
	11/04/81	original version
	07/17/82	fixes for lint
	08/10/82	modest cleanup before posting.
*********************************************************************/

#ifndef lint
 static char Sccsid[] = "@(#)error.c	1.1";
#endif !lint

#include <stdio.h>
#define NOTOK	(-1)

/* VARARGS1 */
error (mesg, args)
char *mesg;
{
	←doprnt (mesg, &args, stderr);
	putc ('\n', stderr);
	exit (NOTOK);
}

extern	errno;
extern	sys←nerr;
extern	char *sys←errlist[];
#ifdef lint
 int	errno;
 int	sys←nerr;
 char *sys←errlist[1];
#endif lint
static	char ehuh[]	= "Unknown System Error";

/* VARARGS1 */
fperror (mesg, args)
char *mesg;
{
	char *err = ((unsigned)errno >= sys←nerr ? ehuh : sys←errlist[errno]);

	←doprnt (mesg, &args, stderr);
	fprintf (stderr, ": %s\n", err);
	exit (NOTOK);
}

/*VARARGS1*/
remark (mesg, args)
char *mesg;
{
	←doprnt (mesg, &args, stderr);
	putc ('\n',stderr);
}

/*VARARGS1*/
fpremark (mesg, args)
char *mesg;
{
	char *err = ((unsigned)errno >= sys←nerr ? ehuh : sys←errlist[errno]);

	←doprnt (mesg, &args, stderr);
	fprintf (stderr, ":%s\n", err);
}
rotate.c
===============================================
char *malloc();

char *rotate (glyph, ht, wd) char *glyph; int ht, wd;
{
    int		byteswide;
    int		oldwidth;
    int		byteoff, bitmask, outbitoff, outbit, posn, i;
    char	*opt, *outptr;
    
    if (ht == 0 || wd == 0) return (glyph);
    byteswide = (ht+7)/8;
    oldwidth = (wd+7)/8;

    opt = malloc (1 + byteswide*wd);
    outptr = opt; *outptr = '\0';
    
    for (posn = 0; posn < wd; posn++)	/* Pick the nth bit off each row */
    {
	bitmask = 1 << (7 - (posn%8) );
	byteoff = posn/8;
	outbitoff = 7;
	for (i = 0; i < ht ; i++)	/* Get from each row... */
	{
	    if (outbitoff < 0) {
		outbitoff = 7;
		outptr++; *outptr = '\0';
	    }
	    outbit =(*(glyph + ((ht-i)-1)*oldwidth + byteoff) & bitmask) != 0;
	    *outptr |= outbit << outbitoff;
	    outbitoff--;
    	}
	outptr++; *outptr = '\0';
    }
    return (opt);
}
special.c
===============================================
#include <stdio.h>
#include "resfonts.h"
#include "imPcodes.h"

#define white(x) (x==' ' || x=='\t')
char *index(),*rindex();

extern int landscape;

typedef char bool;
#define TRUE 1
#define FALSE 0
DoSpecial(bytes,fp) long bytes; FILE *fp;
{
	static bool initfonts=FALSE;
	bool first;
	unsigned long size, tempsize;
	FILE *tempin;
	char *ai,*bi,*ci,*di,*ei,*fi;
	char inchar;	
	int  tempi;
	int  i;
	enum spectype {INSERT, OVERLAY};
	enum spectype optype;

	ai = bi = (char *) malloc((tempsize = bytes)+1);
	while (tempsize--) *bi++=(char) fgetc(fp);
	*bi='\0'; /* null out string */
	bi = ai;
	if (size > 132){
		fprintf(stderr, "special command > 132 characters\n");
		free(ai);
		return;
	}

	while(white(*bi)) bi++;		/* skip leading white space */
	ei = ci = bi;

	if (!index(ei,'(') || !rindex(ei,')')){ 	/* check for leading and trailing *\
			  fprintf(stderr, "incorrect special format\n"); /* prens */
		free(ai);
		return;
	}

	while (!white(*ci) && *ci != '(' ) ci++;  /* skip non white till ( or white */
	*ci='\0';				/* make a string of it */
	while (*ei){				/* and lowercase it all */
		if (*ei >= 'A' && *ei <= 'Z') *ei = *ei + 'a' - 'A';
		ei++;
	}
	if (!strcmp("insert",bi)) 		/* find include, overlay, or */
		optype = INSERT;
	else if (!strcmp("overlay",bi)) 	/* else it is an error */
		optype = OVERLAY;
	else {
		fprintf(stderr,
		"special command operation must be 'insert' or 'overlay'\n");
		free(ai);
		return;
	}

	bi = ++ci;
	while(white(*bi) || *bi == '(' ) bi++;	/* find the file name */
	while(white(*bi)) bi++;
	ci = bi;
	while(!white(*ci) && *ci != ')') ci++;	/* delimited by a ) */
	*ci = '\0';				/* make a string of it */

	if ((tempin = fopen(bi ,"r")) == NULL){	/* open the file */
		fprintf(stderr, " can't open %s \n",bi);
		free(ai);
		return;
	}
	free(ai);				/* no longer need this */

/*	UpdPos(); */
	ImPressPutc(APUSH);
	switch (optype){
/* At the moment, only overlay(file) and insert(file) are
 * recognized.  We use a slightly modified 'impen' (from Stanford
 * via Imagen to produce this stuff, which makes plots come out
 * in landscape mode.  Hence the rotation and stuff.  Other
 * Impress-production software may, of course, behave differently...
 */
	case OVERLAY:				
		ImPressPutc(APAGE);
		if (landscape) {
			ImPressPutc(AMS);
			ImPressPutc(0104);
		}
		else {
			ImPressPutc(ASABSV);
			ImPressBufWord(2040);	/* 8.5 in down */
			ImPressPutc(AMS);
			ImPressPutc(0147);
			ImPressPutc(APAGE);
		}
		break;

	case INSERT:
		ImPressPutc(AMS);
		if (landscape)
			ImPressPutc(0144);
		else
			ImPressPutc(0147);
		break;
	}
	if (!initfonts) {		/* Haven't initialized res fonts */
		for (i=0;i<N←RES←FONTS; i++) {
			ImPressPutc(ACREFAM);
			ImPressPutc(fontTable[i].family);
			ImPressPutc(1);
			ImPressPutc(0);
			ImPressPrintf("%s",fontTable[i].name);
			ImPressPutc(0);
		}
		initfonts=TRUE;
	}
	first = TRUE;
	while ((tempi = getc(tempin)) != EOF) { 	
		inchar = (char) tempi;
		if (inchar ==  '@' && first) {			/* remove document control */
			while (((inchar = getc(tempin)) != EOF)
			          && (inchar != ')' ));
			tempi = getc(tempin);
		}
		first = FALSE;

		ImPressPutc(tempi);
	}
	ImPressPutc(APAGE);
	ImPressPutc(APOP);
}
imPcodes.h
===============================================
/* command codes */

#define	ASP0	128
#define	ASP1	129
#define	AM	130
#define AMP	131
#define	AMM	132

#define ASABSH	135	/* Absolute horizontal */
#define ASABSV	137	/* Absolute vertical   */

#define	ASRULE	192
#define	ABRULE	193

#define	AS	194	/* not implemented yet */
#define	AH	195
#define	AV	196
#define	AN	197

#define	ASGLY	198
#define	ABGLY	199
#define	ADELG	200
#define	ADELC	201
#define	ADELF	202
#define	AFONT	203

#define	APAGOR	204
#define	AMS	205
#define	AROTMS	206

#define	AF	207
#define	ABSKIP	208
#define	AMARGIN	209
#define	ASETSP	210

#define	APUSH	211
#define	APOP	212

#define	APAGE	213
#define	AEND	219

#define ACREFAM	221
#define	ANOP	254
#define	AEOF	255
impress.h
===============================================
/*
 * impress.h
 *
 * header file for finding data bases having to do with the imprint printer
 * by Bill Nowicki, Stanford University, September 1981
 */

# define PixelsPerInch 240		/* Resolution of the printer being used */

  /*
   * size of printable area, 8x10.5 inches
   */
# define PixelsPageHeight ( (int)( PixelsPerInch*10.5 )	)
# define PixelsPageWidth ( PixelsPerInch*8 )

  /*
   * memory parameters
   */
# define K 1024
# define GlyphSize (164*K)	/* size of printer's Glyph buffer */
# define InputSize (24*K)	/* size of printer's input buffer */
# define GlyphsPerPage (10*K)	/* number of distinct glyphs per page */

dvi.h
===============================================
#define SETCHAR0    0
#define SET1        128
#define SETRULE     132
#define PUT1        133
#define PUTRULE     137
#define NOP         138
#define BOP         139
#define EOP         140
#define PUSH        141
#define POP         142
#define RIGHT1      143
#define RIGHT2      144
#define RIGHT3      145
#define RIGHT4      146
#define W0          147
#define W1          148
#define W2          149
#define W3          150
#define W4          151
#define X0          152
#define X1          153
#define X2          154
#define X3          155
#define X4          156
#define DOWN1       157
#define DOWN2       158
#define DOWN3       159
#define DOWN4       160
#define Y0          161
#define Y1          162
#define Y2          163
#define Y3          164
#define Y4          165
#define Z0          166
#define Z1          167
#define Z2          168
#define Z3          169
#define Z4          170
#define FNTNUM0     171
#define FNT1        235
#define FNT2        236
#define FNT3        237
#define FNT4        238
#define XXX1        239
#define XXX2        240
#define XXX3        241
#define XXX4        242
#define FNTDEF1     243
#define FNTDEF2     244
#define FNTDEF3     245
#define FNTDEF4     246
#define PRE         247
#define POST        248
#define POSTPOST    249

#define TRAILER     223     /* Trailing bytes at end of file */
c.h
===============================================
/*
 * Standard C macros
 *
 **********************************************************************
 * HISTORY
 * 23-Apr-81  Mike Accetta (mja) at Carnegie-Mellon University
 *	Added "sizeofS" and "sizeofA" macros which expand to the size
 *	of a string constant and array respectively.
 *
 **********************************************************************
 */

#define ABS(x)		((x) >= 0 ? (x):-(x))
#define MAX(a,b)	((a) > (b) ? (a):(b))
#define MIN(a,b)	((a) < (b) ? (a):(b))

#define FALSE		0
#define TRUE		1
#define	CERROR		(-1)

#define	sizeofS(string)	(sizeof(string) - 1)
#define sizeofA(array)	(sizeof(array)/sizeof(array[0]))
font.h
===============================================
/*
 * font.h - some definitions for the font manipulation routines
 *           **CHANGED at Cornell for the dvi-imagen program **
 *
 * Note that our terminology is slightly different from that of Knuth
 * and Parc. Since TROFF assumes that fonts are scalable, we must
 * use a single Knuth font (which we call a family, similar to a Parc face),
 * at different magnifications (which is what we call a "font").
 */


/*
 * the layout of a font information block
 * There is one of these for every loaded "font", or
 * magnification thereof in Knuthian terms.
 *
 * Also note the strange units.  The design size is in 1/2↑20 point
 * units (also called micro-points), and the individual character widths
 * are in the TFM file in 1/2↑20 ems units, i.e. relative to the design size.
 */

# define TwoToTheTwenty (1024*1024)
# define MAXCHARS 256		/* make 128 for 7 bit characters */

enum CharStatus {NotThere, Ready, Loaded, Wanted, Kept, InProm};

struct font
 {
    struct font * next;   	/* link to next font info block            */
    int Inumber;   		/* font number (on Imagen)                 */
    int TeXnumber;              /* font number (in DVI file)               */
    int scale;             	/* scaled size in DVI units                */
    int design;               	/* design size in DVI units                */

    unsigned char bc;       	/* beginning char defined                  */
    unsigned char ec;       	/* ending char defined                     */

    enum CharStatus state[ MAXCHARS ];
    	    			/* loaded, existant, or in Prom??          */

				/* following are in pixels                 */
    short H[ MAXCHARS ];    	/* height for each glyph raster            */
    short W[ MAXCHARS ];    	/* width for each glyph raster             */
    short Y[ MAXCHARS ];    	/* Y-offset for each glyph raster          */
    short X[ MAXCHARS ];    	/* X-offset for each glyph raster          */
    short pxl←adv[ MAXCHARS ];	/* pixels to move reference point          */
    long  dvi←adv[ MAXCHARS ];	/* DVI units to move reference point       */

    char  *Glyph[ MAXCHARS ];	/* pointers to actual glyph bitmaps        */
    char  fontname[100];
 };

extern struct font *fontListHead; /* head of linked list of font structures */
int debug;			        /* true for debugging information */
ipr.h
===============================================
/*
 * ipr.h -- ImPress printer spooler definitions
 *
 * by Bill Nowicki September 29, 1981
 * at Stanford University for Imagen Corporation
 */

# define SPOOLDIR "/usr/spool/ipd"		/* the spooling directory */
# define LOCK     "/usr/spool/ipd/lock"		/* the lock file  */
# define LOG      "/tmp/implog"		/* the error log file  */
# define DAEMON   "/usr/local/lib/imagen/ipd"		/* the unqueuing daemon */
# define PRINTING "/usr/local/lib/imagen/ips"		/* the printing program */
# define COMMAND  "/usr/local/bin/ipr"		/* the command for enqueing */
# define WRITE    "/usr/local/lib/imagen/dwrite"		/* write to a user */
# define HUMAN    "ImPress printer Daemon"	/* Human understandable name */
# define KIND	  "ImPrint"			/* kind of printer we use */

# define LOCKTIMEOUT	5*60		/* seconds for the lock timeout */

# define LineSize 128			/* size of a data line */

# include <sys/types.h>
# include <sys/dir.h>
# include <sys/stat.h>
# include <sys/signal.h>
# include <stdio.h>
# include "c.h"
# define bool int

/*
 * I am not sure if the following is documented anywhere, so
 * I thought I would include it here so nonone else has to go through
 * what I did to discover how the standard spooling stuff works.
 * I also added a few of my own codes, which should not conflict
 * with anything.
 *
 * Basically there are files in the spool directory of the form:
 * dfXXXXXa (where XXXXX is the pid), that have lines with a one
 * character code followed by informational lines:
 *	B	treated like F in ipq.c
 *	C	number of copies to print
 *	F	File name to print
 *	L	User's name responsible for printing
 *	M	Mail address to inform when printing is complete
 *	N	User to notify when printing is complete
 *	P	Pages in body (total)
 *	R	"Real" user name for cover sheet
 *	T	"Tag" to identify this job, usually the file name
 *	U	File to unlink after finishing
 */

extern int debug;	/* for extra debugging messages */

int Copies;		/* number of copies to print */
int Pages;		/* number of pages (approx) */
resfonts.h
===============================================
#define TEXTURE←FAMILY 110
#define N←RES←FONTS  8

typedef struct {
	short family;
	char *name;
	}  resfont;


resfont fontTable[]= {
	{	TEXTURE←FAMILY+0,	"textures"},
	{	TEXTURE←FAMILY+1,	"cmasc8"},
	{	TEXTURE←FAMILY+2,	"cmasc10"},
	{	TEXTURE←FAMILY+3,	"cmasc12"},
	{	TEXTURE←FAMILY+4,	"cmasc14"},
	{	TEXTURE←FAMILY+5,	"cmasc7"},
	{	TEXTURE←FAMILY+6,	"cmb18"},
	{	TEXTURE←FAMILY+7,	"IMAGEN80"}
};